package org.codetranslators.common;

import org.codetranslators.compiler.intermrep.AssemblyInstruction;

import java.util.BitSet;
import java.util.Vector;
import java.util.HashSet;

public class ControlFlowNode extends Node{
	private Vector instructions;      // The list of instructions in this node
	HashSet definitions;              // The list of variables that have been defined in this node

	//	Use and def temporaries in the form of a bit vectors for liveness analysis
	private BitSet usesBitVector;
	private BitSet defsBitVector;

	public ControlFlowNode(){
		definitions = new HashSet();
	}

	public ControlFlowNode(Vector instrs){		
		this.instructions = instrs;

		// Populate the temporaries defined in this node
		populateDefinitionsInNode();
	}

	public void populateDefinitionsInNode(){
		for(int i = 0; i < instructions.size(); i++){
			AssemblyInstruction instr = (AssemblyInstruction) instructions.elementAt(i);
			Vector listOfDefinedVariables = instr.getDestList();
			if(listOfDefinedVariables != null){
				for(int j = 0; j < listOfDefinedVariables.size(); j++){
					Temp temp = (Temp) listOfDefinedVariables.elementAt(j);
					definitions.add(temp);
				}
			}
		}
	}

	public Vector getInstructions() {
		return instructions;
	}

	public HashSet getDefinitions() {
		return definitions;
	}

	public void setInstructions(Vector instructions) {
		this.instructions = instructions;
		populateDefinitionsInNode();
	}

	/*
	 * This function removes the instruction that has been passed. This can be called from
	 * optimization routines that discover that an instruction is unnecessary (maybe during dead
	 * code elimination).
	 */
	public void removeInstruction(AssemblyInstruction instr){
		instructions.remove(instr);
	}

	public void displayNode(){
		System.out.println("Node " + getName() + ":");
		for(int i = 0; i < instructions.size(); i++) {
			AssemblyInstruction assemInstr = (AssemblyInstruction) instructions.elementAt(i);
			System.out.println(assemInstr.getAssemCode(false).trim());
		}
	}

	/*
	 * Returns a clone of this instance of the ControlflowNode. Used in creating a new controlFlowGraph
	 * from a given control flow graph with some special properties -namely, a reverse control flow graph)
	 *
	 */
	public ControlFlowNode createClone(){
		ControlFlowNode clone = new ControlFlowNode();

		clone.setInstructions(instructions);
		clone.setName(getName());

		return clone;
	}

	public BitSet getDefsBitVector()
	{
		return defsBitVector;
	}

	public void setDefsBitVector(BitSet defsBitVector)
	{
		this.defsBitVector = defsBitVector;
	}

	public BitSet getUsesBitVector()
	{
		return usesBitVector;
	}

	public void setUsesBitVector(BitSet usesBitVector)
	{
		this.usesBitVector = usesBitVector;
	}

	public void setFromXml(boolean b) {
		// TODO Auto-generated method stub

	}
}
